package com.wdl.report.app.utils;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

/**
 * Created by bysd-2 on 2018/10/19.
 */

public class BlueToothHelper {
    public static final int REQUEST_BLUE_ENABLE = 110;
    private static Context mContext;
    private static BluetoothAdapter bluetoothAdapter;
    private static String UUID_STR = "00001101-0000-1000-8000-00805F9B34FB";
    public static CURR_STATUS curr_status;
    private static ConnectThread connectThread;
    private static ReadThread readThread;
    private static SendThread sendThread;
    private static Handler queueMsg;


    public enum CURR_STATUS {
        CONNECTED, DISCONNECTED
    }

    // 初始化   这里需要注意是蓝牙如果没有开启则要开启后 在activity回调里再次获取发现搜索一下设备；
    public static BluetoothAdapter initBlueTooth(Context context, Activity currActivity) {
        mContext = context;
        BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        bluetoothAdapter = bluetoothManager.getAdapter();
        if (bluetoothAdapter != null) {
            if (!bluetoothAdapter.isEnabled()) {
                Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
//                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                currActivity.startActivityForResult(intent, REQUEST_BLUE_ENABLE);
            }
            return bluetoothAdapter;
        } else {
            return null;
        }
    }

    // 初始化后可以调用此方法，还有在activity回调成功时调用；    此处还需要一个广播来接收相应的消息，这个广播我稍后发出来    ，广播其实也可以放到此工具类里，我只是分出来了，放到这个工具类里好处时各个状态比较好监听，放到外面则需要两个监听，有些多余；
    public static void startDiscover() {
        if (bluetoothAdapter != null) {
            if (bluetoothAdapter.isDiscovering()) {
                bluetoothAdapter.cancelDiscovery();
                bluetoothAdapter.startDiscovery();
            } else {
                bluetoothAdapter.startDiscovery();
            }
        }
    }

    // 这个在连接之前，扫描设备超时的时候调用；节省资源；
    public static void cancelDiscover() {
        if (bluetoothAdapter != null) {
            bluetoothAdapter.cancelDiscovery();
        }
    }

    // 退出的时候调用，释放及重置
    public static void close() {
        if (bluetoothSocket != null) {
            try {
                bluetoothSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bluetoothAdapter != null) {
            bluetoothAdapter = null;
        }
        if (connectThread != null) {
            connectThread = null;
        }
        if (readThread != null) {
            readThread = null;
        }
        if (sendThread != null) {
            sendThread = null;
        }
        //
        curr_status = CURR_STATUS.DISCONNECTED;

    }

    //  连接时的回调； 里面加了一个接收数据的回调；
    public static IConnectListener iConnectListener;

    public interface IConnectListener {
        void connectDevSuccess();//连接成功；

        void connectDevFail(String exception); // 连接出错；

        void dataRespon(byte[] bytes); // 接收
    }

    // connect
    public static void connectDevice(IConnectListener l, BluetoothDevice device) {
        iConnectListener = l;
        //
        if (connectThread == null) {
            connectThread = new ConnectThread(device);
            connectThread.start();
        } else {
            Log.e(TAG, "connectThread != null");
        }
    }

    private static final String TAG = BlueToothHelper.class.getSimpleName();
    //
    private static InputStream inS = null;
    private static OutputStream outs = null;
    private static BluetoothSocket bluetoothSocket;
    private static final int SEND_CONNECT_FAIL = 1;
    private static final int SEND_CONNECT_SUCCESS = 2;
    private static final int SEND_FLAG = 110;

    static class ConnectThread extends Thread {
        private BluetoothDevice device;

        public ConnectThread(BluetoothDevice device) {
            this.device = device;
        }

        @Override
        public void run() {
            super.run();
            //
            try {
                UUID uuid = UUID.fromString(UUID_STR);
                BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(device.getAddress());
                // // TODO: 2018/10/23  此处通过uuid连接蓝牙；但有时候连接不上，不能保证每次都可以连接上；
                bluetoothSocket = remoteDevice.createRfcommSocketToServiceRecord(uuid); // RFcomm 是一种简单的传输协议
                bluetoothSocket.connect();
                // 靠谱的方式；  这种是比较暴力的方式，直接连蓝牙，API没有开放，估计是为了安全的角度，通过信道连接，范围1-30； 通过递归直到练到正确的信道上；
//                bluetoothSocket = cretateBluetoothSocketbyChannel(remoteDevice, 1, true);
                if (bluetoothSocket == null) {
                    sendMSG(SEND_CONNECT_FAIL, "0: " + "change channel always error");
                    return;
                }
                Log.e(TAG, "ok");
                //
                inS = bluetoothSocket.getInputStream();
                outs = bluetoothSocket.getOutputStream();

            } catch (IOException e) {
                e.printStackTrace();
                try {
                    if (bluetoothSocket != null) {
                        bluetoothSocket.close();
                    }
                    if (inS != null) {
                        inS.close();
                    }
                    if (outs != null) {
                        outs.close();
                    }
                    bluetoothSocket = null;
                    inS = null;
                    outs = null;
                } catch (IOException e1) {
                    e1.printStackTrace();
                    //
                    sendMSG(SEND_CONNECT_FAIL, "1: " + e.getMessage());
                    return;
                }
                //
                sendMSG(SEND_CONNECT_FAIL, "2: " + e.getMessage());
                return;
            }
            //
            sendMSG(SEND_CONNECT_SUCCESS, null);

        }
    }


    /**
     * 有时候用api提供的方法remoteDevice.createRfcommSocketToServiceRecord(uuid)不能成功连接，connect总出错误；
     *
     * @param Device
     * @param channel
     * @param autoForward
     * @return
     */
    private static BluetoothSocket cretateBluetoothSocketbyChannel(BluetoothDevice Device, int channel, boolean autoForward) {
        BluetoothSocket socket = null;
        try {
            // createRfcommSocket为内置方法，入参为int类型； invoke执行该方法并需传入当前类对象及所需的入参类型；得到该方法的返回；
            socket = (BluetoothSocket) Device.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(Device, Integer.valueOf(channel));
            socket.connect();
            Log.e(TAG, "connect is ok .  " + channel);
        } catch (Exception e) {
            Log.e(TAG, "get socket is failed . e: " + e.getMessage());
            if (channel < 30) {
                if (autoForward) {
                    socket = cretateBluetoothSocketbyChannel(Device, channel + 1, autoForward);
                }
            } else {
                return null;
            }
        }
        return socket;
    }

    private static void sendMSG(int what, Object object) {
        Message msg = mHandler.obtainMessage();
        msg.what = what;
        msg.obj = object;
        mHandler.sendMessage(msg);
    }

    private static Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SEND_CONNECT_FAIL:
                    if (iConnectListener != null) {
                        iConnectListener.connectDevFail((String) msg.obj);
                    }
                    //
                    curr_status = CURR_STATUS.DISCONNECTED;
                    break;
                case SEND_CONNECT_SUCCESS:
                    //
                    curr_status = CURR_STATUS.CONNECTED;
                    //
                    if (iConnectListener != null) {
                        iConnectListener.connectDevSuccess();
                    }
                    //
                    if (readThread == null) {
                        readThread = new ReadThread();
                        readThread.start();
                    } else {
                        Log.e(TAG, "readThread != null");
                    }
                    //
                    if (sendThread == null) {
                        sendThread = new SendThread();
                        sendThread.start();
                    }
                    break;
            }
        }
    };

    static class SendThread extends Thread {

        @Override
        public void run() {
            super.run();
            //
            Looper.prepare();
            queueMsg = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    if (msg.what == SEND_FLAG) {
                        byte[] bytes = (byte[]) msg.obj;
                        sendToBlt(bytes);
                    }
                    super.handleMessage(msg);
                }
            };
            Looper.loop();
        }
    }

    static class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            if (curr_status == CURR_STATUS.CONNECTED) {
                if (inS == null) {
                    return;
                }
                try {
                    int available = inS.available();
                    byte[] bRec = new byte[available];
                    int read = inS.read(bRec);
                    //
                    Log.e(TAG, "rece ///  available: " + available + "   read: " + read);
                    if (read > 0) {
                        if (iConnectListener != null) {
                            iConnectListener.dataRespon(bRec);
                        }
                    }
                    Thread.sleep(200);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 蓝牙发送  会放到队列里；
    public static void sendData(byte[] data) {
        if (queueMsg != null) {
            Message message = queueMsg.obtainMessage();
            message.what = SEND_FLAG;
            message.obj = data;
            queueMsg.sendMessage(message);
        }
    }

    private static void sendToBlt(byte[] data) {
        if (curr_status == CURR_STATUS.CONNECTED) {
            try {
                Log.e(TAG, "send data");
                outs.write(data);
            } catch (IOException e) {
                Log.e(TAG, "e: " + e.getMessage());
                e.printStackTrace();
            }
        } else {
            Log.e(TAG, "sendToBlt is fail...");
        }
    }

}
